package satir.command;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.NoSuchElementException;
import java.util.Scanner;

import satir.SatirGame;
import satir.card.Deck;
import satir.card.MagicToolCard;
import satir.card.RoleCard;
import satir.framework.InputValidator;
import satir.framework.LazyInitiator;
import satir.player.Player;

/**
 * The Class PickRoleCmd.
 * @version 3.0 April 2012
 * @author Creative Family
 */

public class PickRoleCmd implements Command {

    /** The satir game. */
    private SatirGame satirGame;

    /** variable to store user input temporarily. */
    private Scanner scanner;

    /** role. */
    private String[] role = {"Grandfather", "Grandmother", "Father", "Mother",
	    "Son", "Daughter" }; // Define the role

    /** role card name. */
    private String[] roleCardName;

    /** list of role cards. */
    private ArrayList<RoleCard> roleCards; // Current role card list

    /** Deck to hold magic tool card. */
    private Deck magicToolDeck;

    /** number for role card. */
    private String[] cardNumber; // Current card number

    /** Player object. */
    private Player player; // Current player

    /** RoleCard object. */
    private RoleCard roleCard; // Blank role card

    /** number of player. */
    private int numOfPlayer;

    /** The count. */
    private int count = 1;

    /**
     * Initialize a PickRoleCmd object for user input.
     */

    public PickRoleCmd() {
	scanner = new Scanner(System.in);
    }

    /**
     * Instantiates a new pick role cmd.
     * @param satirGame
     *            the satirGame object
     */
    public PickRoleCmd(final SatirGame satirGame) {
	this();
	this.satirGame = satirGame;
	magicToolDeck = (Deck) LazyInitiator.get("MagicToolDeck",
		"MagicToolCard", true);
    }

    /**
     * pick Role Card.
     */
    public void execute() {
	numOfPlayer = satirGame.getNumOfPlayer();
	roleCards = satirGame.getArrayListRoleCard();
	String line;
	int cardNum = 0;
	int index = 0;
	// player will get same number of magic tool card
	int holdMagicToolCard = magicToolDeck.getSize() / numOfPlayer;
	arrangeRoleCard();

	for (int i = 0; i < numOfPlayer; i++) {
	    player = satirGame.getPlayers(i);
	    roleCard = roleCards.get(i);
	    System.out.println(player.getName()
		    + ", Please choose the card No.");
	    for (int j = 0; j < roleCards.size(); j++) {
		System.out.print("--");
	    }
	    System.out.println("-");
	    for (int j = 0; j < cardNumber.length; j++) {
		System.out.print("|" + cardNumber[j]);
	    }
	    System.out.println("|");
	    for (int j = 0; j < cardNumber.length; j++) {
		System.out.print("--");
	    }
	    System.out.println("-");
	    try {
		while (true) {
		    System.out.print("Card No. ");
		    line = scanner.next();
		    if (line != null) {
			if (InputValidator.isInteger(line)) {
			    index = Integer.parseInt(line);
			} else {
			    System.out.println("It is not a number.");
			    continue;
			}
		    }
		    if (!InputValidator.isWithinRange(index, 1,
			    cardNumber.length)) {
			// wrong input
			System.out.println("The number is out of range.");
			continue;
		    } else if (cardNumber[index - 1] == "X") {
			// that role card have be taken
			System.out.println("The number is not available.");
			continue;
		    } else {
			break;
		    }
		}
		roleCard.setName(roleCardName[index - 1]);
		player.setRole(roleCard);

		for (int j = 0; j < holdMagicToolCard; j++, cardNum++) {
		    // player.setMtCards(magicToolCards.get(cardNum)); //assign
		    // magic tool card to player
		    player.setMtCards((MagicToolCard) magicToolDeck.drawCard());
		}
		System.out.println("Result: " + player.getName() + " & Role : "
			+ player.getRole().getName());
		System.out.println("Magic Tool Card : ");
		for (int k = 0; k < player.getMtCards().size(); k++) {
		    // show to player that what magic tool card they have
		    System.out.print(player.getMtCards().get(k).getName()
			    + " | ");
		}
		System.out.println();
		count++;
		if (count <= numOfPlayer) {
		    this.clearCard(index - 1);
		}
	    } catch (NoSuchElementException e) {
		e.printStackTrace();
	    }
	}
    }

    /**
     * Sets detail to player.
     * @param player
     *            player object
     */
    public void setPlayer(final Player player) {
	this.player = player;
    }

    /**
     * Sets role cards to player.
     * @param roleCard
     *            roleCard object
     */
    public void setCard(final RoleCard roleCard) {
	this.roleCard = roleCard;
    }

    /**
     * Sets magic tool card to player.
     * @param mtCard
     *            MagicToolCard object
     */
    public void setCard(final MagicToolCard mtCard) {
	player.setMtCards(mtCard);
    }

    /**
     * Sets the number of player.
     * @param numOfPlayer
     *            number of player
     */
    public void setNumOfPlayer(final int numOfPlayer) {
	this.numOfPlayer = numOfPlayer;
    }

    // Arrange the current role card list
    /**
     * Arrange role card as number.
     */
    public void arrangeRoleCard() {
	/*
	 * if there are only 2-4 player, the role of "grandfather" and
	 * "grandmother" is not available to choose
	 */
	if (numOfPlayer >= 2 && numOfPlayer <= 4) {
	    roleCardName = new String[4];
	    cardNumber = new String[4];
	    for (int i = 2; i < 6; i++) {
		roleCardName[i - 2] = role[i];
	    }

	    for (int i = 0; i < 4; i++) {
		cardNumber[i] = Integer.toString(i + 1);
	    }
	} else {
	    roleCardName = role;
	    cardNumber = new String[6];
	    for (int i = 0; i < 6; i++) {
		cardNumber[i] = Integer.toString(i + 1);
	    }
	}
    }

    // Change the card number to X of the card which is chosen and rearrange the
    // current role card list
    /**
     * Clear the card after being chosen.
     * @param index
     *            number being chosen
     */
    public void clearCard(final int index) {
	cardNumber[index] = "X"; // showing that card have been chosen by "X"
	if (numOfPlayer == 2) {
	    boolean isParentChoosed = false;
	    for (int i = 0; i < cardNumber.length; i++) {
		if (cardNumber[i] == "X"
			&& (roleCardName[i] == "Father" || roleCardName[i] == "Mother")) {
		    isParentChoosed = true;
		}
	    }
	    roleCardName = new String[2];
	    /*
	     * if there is only two players and one is being parent, another one
	     * must be a children
	     */
	    if (isParentChoosed) {
		for (int i = 4; i < 6; i++) {
		    roleCardName[i - 4] = role[i];
		}
		/*
		 * if there is only two players and one is being children,
		 * another one must be a parent
		 */
	    } else {
		for (int i = 2; i < 4; i++) {
		    roleCardName[i - 2] = role[i];
		}
	    }
	    cardNumber = new String[2];
	    for (int i = 0; i < 2; i++) {
		cardNumber[i] = Integer.toString(i + 1);
	    }
	}
    }
}
